package com.coai.twin.service

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.springframework.stereotype.Service

/**
 * 虚拟业务模拟引擎
 */
@Service
class SimulationEngine(
    private val influxDBService: InfluxDBService
) {
    
    /**
     * What-If分析
     */
    suspend fun runWhatIfAnalysis(
        scenario: SimulationScenario
    ): SimulationResult = withContext(Dispatchers.IO) {
        
        // 基于历史数据模拟不同场景
        try {
            // 1. 加载历史数据
            val historicalData = loadHistoricalData(scenario.name)
            
            // 2. 应用场景参数
            val baseMetrics = calculateBaseMetrics(historicalData)
            val adjustedMetrics = applyScenarioAdjustments(baseMetrics, scenario.parameters)
            
            // 3. 生成预测结果
            val predictions = mutableMapOf<String, Double>()
            
            // 处理不同类型的参数调整
            scenario.parameters.forEach { (key, value) ->
                when (key) {
                    "orderIncrease" -> {
                        val increase = (value as? Number)?.toDouble() ?: 0.0
                        predictions["throughput"] = baseMetrics["throughput"]!! * (1 + increase)
                        predictions["responseTime"] = baseMetrics["responseTime"]!! * (1 + increase * 0.5)
                        predictions["errorRate"] = baseMetrics["errorRate"]!! * (1 + increase * 0.3)
                    }
                    "resourceIncrease" -> {
                        val increase = (value as? Number)?.toDouble() ?: 0.0
                        predictions["throughput"] = baseMetrics["throughput"]!! * (1 + increase * 1.5)
                        predictions["responseTime"] = baseMetrics["responseTime"]!! * (1 - increase * 0.3)
                    }
                    "peakTraffic" -> {
                        val multiplier = (value as? Number)?.toDouble() ?: 1.0
                        predictions["throughput"] = baseMetrics["throughput"]!! * multiplier
                        predictions["responseTime"] = baseMetrics["responseTime"]!! * (multiplier * 0.8)
                        predictions["errorRate"] = baseMetrics["errorRate"]!! * (multiplier * 0.5)
                    }
                }
            }
            
            // 4. 生成建议
            val recommendations = generateRecommendations(adjustedMetrics, predictions)
            
            SimulationResult(
                scenarioName = scenario.name,
                predictedMetrics = predictions.ifEmpty { adjustedMetrics },
                recommendations = recommendations
            )
        } catch (e: Exception) {
            logger.error("Failed to run what-if analysis", e)
            SimulationResult(
                scenarioName = scenario.name,
                predictedMetrics = mapOf(
                    "throughput" to 1200.0,
                    "responseTime" to 150.0,
                    "errorRate" to 0.01
                ),
                recommendations = listOf("模拟失败，请检查参数")
            )
        }
    }
    
    private fun loadHistoricalData(scenarioName: String): Map<String, List<Double>> {
        // 模拟加载历史数据
        return mapOf(
            "throughput" to listOf(1000.0, 1050.0, 980.0, 1020.0),
            "responseTime" to listOf(100.0, 105.0, 98.0, 102.0),
            "errorRate" to listOf(0.008, 0.009, 0.007, 0.008)
        )
    }
    
    private fun calculateBaseMetrics(historicalData: Map<String, List<Double>>): Map<String, Double> {
        return historicalData.mapValues { (_, values) ->
            values.average()
        }
    }
    
    private fun applyScenarioAdjustments(
        baseMetrics: Map<String, Double>,
        parameters: Map<String, Double>
    ): Map<String, Double> {
        return baseMetrics.toMutableMap()
    }
    
    private fun generateRecommendations(
        current: Map<String, Double>,
        predicted: Map<String, Double>
    ): List<String> {
        val recommendations = mutableListOf<String>()
        
        // 比较当前和预测值
        predicted.forEach { (key, value) ->
            val currentValue = current[key] ?: 0.0
            val change = ((value - currentValue) / currentValue * 100)
            
            when (key) {
                "throughput" -> {
                    if (change > 20) {
                        recommendations.add("吞吐量将增加${change.toInt()}%，建议提前扩容资源")
                    }
                }
                "responseTime" -> {
                    if (change > 50) {
                        recommendations.add("响应时间可能增加${change.toInt()}%，建议优化数据库查询")
                    }
                }
                "errorRate" -> {
                    if (change > 30) {
                        recommendations.add("错误率可能上升，建议增加错误处理机制")
                    }
                }
            }
        }
        
        if (recommendations.isEmpty()) {
            recommendations.add("系统运行稳定，无需特别调整")
        }
        
        return recommendations
    }
    
    /**
     * 运行业务模拟
     */
    suspend fun runSimulation(
        parameters: Map<String, Double>,
        duration: Int
    ): List<SimulationStep> = withContext(Dispatchers.IO) {
        
        val steps = mutableListOf<SimulationStep>()
        
        for (i in 1..duration) {
            val step = SimulationStep(
                time = i,
                metrics = mapOf(
                    "orders" to (100 + i * 10).toDouble(),
                    "revenue" to (10000 + i * 1000).toDouble()
                )
            )
            steps.add(step)
        }
        
        steps
    }
    
    /**
     * 获取实时KPI
     */
    fun getRealTimeKPIs(): Map<String, Double> {
        
        // 从InfluxDB查询实时指标
        val metrics = mutableMapOf<String, Double>()
        
        // 消息量
        val messageCount = queryMetric("SELECT SUM(value) FROM message_count WHERE time > now() - 1h")
        metrics["hourly_messages"] = messageCount
        
        // 文件上传量
        val fileCount = queryMetric("SELECT SUM(value) FROM file_count WHERE time > now() - 1h")
        metrics["hourly_files"] = fileCount
        
        // 通话时长
        val callDuration = queryMetric("SELECT SUM(value) FROM call_total_duration WHERE time > now() - 1h")
        metrics["hourly_call_minutes"] = callDuration / 60
        
        // 仓储订单
        val warehouseOrders = queryMetric("SELECT SUM(value) FROM warehouse_order_count WHERE time > now() - 1h")
        metrics["hourly_warehouse_orders"] = warehouseOrders
        
        return metrics
    }
    
    private fun queryMetric(query: String): Double {
        val results = influxDBService.query(query)
        return results.firstOrNull()?.get("sum") as? Double ?: 0.0
    }
}

data class SimulationScenario(
    val name: String,
    val parameters: Map<String, Double>
)

data class SimulationResult(
    val scenarioName: String,
    val predictedMetrics: Map<String, Double>,
    val recommendations: List<String>
)

data class SimulationStep(
    val time: Int,
    val metrics: Map<String, Double>
)
